# 车牌识别
import cv2
import numpy as np

# Step 1: Load the Image
# 加载图像文件。如果路径不正确，image 将为 None。
image = cv2.imread('car.jpg')  # 请将此路径替换为你的图像文件路径
# 将彩色图像转换为灰度图像以减少计算复杂性，因为灰度图像只有单通道。
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

# Step 2: Pre-processing
# 预处理阶段
# 使用高斯模糊处理灰度图像以减少噪声。这一步可以平滑图像，使边缘检测更加准确。
blur = cv2.GaussianBlur(gray, (5, 5), 0)

# 使用 Canny 算法进行边缘检测。Canny 边缘检测是一个常用的算法，输入模糊图像后可以有效地检测边缘。
# 参数 100 和 200 是边缘检测的阈值，它们决定了边缘的强度。
edges = cv2.Canny(blur, 100, 200)

# Step 3: Find Contours
# 寻找图像中的轮廓。这里我们使用 RETR_TREE 模式，它会返回所有轮廓的分层结构。
# CHAIN_APPROX_SIMPLE 用于压缩轮廓的水平、垂直和对角线段，只保留端点。
contours, _ = cv2.findContours(edges, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

# Step 4: Filter for License Plate Shape
# 定义一个变量以存储可能的车牌轮廓
plate_contour = None
for contour in contours:
    # 计算轮廓的近似多边形
    # epsilon 表示近似精度，0.02 * cv2.arcLength(contour, True) 指的是轮廓周长的 2%
    epsilon = 0.02 * cv2.arcLength(contour, True)
    approx = cv2.approxPolyDP(contour, epsilon, True)

    # 检查轮廓是否为四边形。若有四个角，则可能为矩形或近似矩形
    if len(approx) == 4:
        # 获取轮廓的外接矩形
        x, y, w, h = cv2.boundingRect(approx)

        # 计算矩形的长宽比。一般车牌的长宽比在 2 到 5 之间（因国家不同而异）
        aspect_ratio = w / h
        if 2 < aspect_ratio < 5:  # 如果符合车牌的粗略长宽比
            plate_contour = approx  # 保存该轮廓
            break  # 停止循环，因为我们已经找到了一个可能的车牌

# Step 5: Extract and Recognize License Plate Region
# 如果找到了车牌轮廓，则提取该区域
if plate_contour is not None:
    # 获取外接矩形的坐标
    x, y, w, h = cv2.boundingRect(plate_contour)

    # 提取车牌区域的图像，这里是灰度图像的子区域
    plate_region = gray[y:y + h, x:x + w]

    # 在此处可以对车牌区域进行进一步处理，比如使用 SVM 进行字符识别，或者使用 OCR（光学字符识别）
    # 例如，可以使用 Tesseract OCR 来识别字符
    # import pytesseract
    # text = pytesseract.image_to_string(plate_region)
    # print("License Plate Text:", text)  # 输出识别到的车牌文本

    # 显示检测到的车牌区域
    cv2.imshow("License Plate", plate_region)
    cv2.waitKey(0)  # 等待按键以关闭窗口

# 销毁所有窗口以释放资源
cv2.destroyAllWindows()
